package org.jeecg.modules.front.controller;

import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ValidationException;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.modules.front.entity.vo.BuyOrder;
import org.jeecg.modules.front.entity.vo.PayOrder;
import org.jeecg.modules.front.entity.vo.WxNotification;
import org.jeecg.modules.front.util.AliUtil;
import org.jeecg.modules.front.util.WechatConfigUtil;
import org.jeecg.modules.front.util.WechatUtil;
import org.jeecg.modules.gongqiang.entity.*;
import org.jeecg.modules.gongqiang.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @Author scott
 * @since 2018-12-17
 */
@RestController
@RequestMapping("/front/order")
@Api(tags = "前台用户基础模块")
@Slf4j
public class FrontOrderController {
    @Autowired
    private IGoodTypeService goodTypeService;
    @Autowired
    private IGoodService goodService;
    @Autowired
    private IUserhomeOrderService userhomeOrderService;
    @Autowired
    private IGoodDetailService goodDetailService;
    @Autowired
    private ISerialNumberService serialNumberService;


    @ApiOperation("订单查询")
    @RequestMapping(value = "/show", method = RequestMethod.GET)
    public Result<Integer> showOrder(@RequestParam String orderId, HttpServletRequest req) {
        UserhomeOrder userhomeOrder = userhomeOrderService.getById(orderId);
        if (userhomeOrder == null) {
            return Result.ok(-1);
        }
        return Result.ok(userhomeOrder.getStatus());
    }

    @ApiOperation("下单")
    @RequestMapping(value = "/buy", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public Result<UserhomeOrder> createOrder(@RequestBody BuyOrder buyOrder, HttpServletRequest req) {
        GoodDetail goodDetail = goodDetailService.getByIdLock(buyOrder.getGoodDetailId());
        if (goodDetail == null) {
            return Result.error("商品已下架!");
        }
        if (goodDetail.getStockNum() < buyOrder.getNum()) {
            return Result.error("商品库存不足!");
        }
        Good good = goodService.getById(goodDetail.getGoodId());
        if (good == null) {
            return Result.error("商品已下架!");
        }
        if (!good.getStatus().equals(1)) {
            return Result.error("商品已下架!");
        }
        goodDetail.setStockNum(goodDetail.getStockNum() - buyOrder.getNum());
        goodDetailService.updateById(goodDetail);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
        String orderNum = "O" + dateFormat.format(new Date()) + RandomUtil.randomNumbers(6);
        Integer userId = JwtUtil.getUserId(req.getHeader("X-Access-Token"));
        UserhomeOrder userhomeOrder = new UserhomeOrder();
        userhomeOrder.setCreateBy("自行购买");
        userhomeOrder.setCreateTime(new Date());
        userhomeOrder.setUpdateBy("执行下单");
        userhomeOrder.setUpdateTime(new Date());
        userhomeOrder.setGoodId(good.getId());
        userhomeOrder.setGoodDetailId(goodDetail.getId());
        userhomeOrder.setNum(buyOrder.getNum());
        userhomeOrder.setTprice(goodDetail.getPrice() * buyOrder.getNum());
        userhomeOrder.setRemark("下单未支付");
        userhomeOrder.setPayType(0);
        userhomeOrder.setUserId(userId);
        userhomeOrder.setOrderNum(orderNum);
        userhomeOrder.setStatus(0);
        userhomeOrder.setGoodCode(good.getGoodCode());
        userhomeOrder.setGoodDetailPrice(goodDetail.getPrice());
        userhomeOrder.setGoodDetailMarketPrice(goodDetail.getMarketPrice());
        userhomeOrder.setGoodDetailTermId(goodDetail.getTermId());
        userhomeOrder.setGoodPcUrl(good.getPcUrl());
        userhomeOrderService.save(userhomeOrder);
        return Result.ok(userhomeOrder);
    }

    @RequestMapping(value = "/wx/notify", method = RequestMethod.POST)
    @Transactional(rollbackFor = Exception.class)
    public String wxNotify(@RequestBody String requestBody, HttpServletRequest req) throws InstantiationException, IllegalAccessException {
        WxNotification wxNotification = JSON.parseObject(requestBody, WxNotification.class);
        if (wxNotification.getEventType().equals("TRANSACTION.SUCCESS") && wxNotification.getResourceType().equals("encrypt-resource")) {
            //支付成功
            String wechatPaySerial = req.getHeader("Wechatpay-Serial");
            String wechatpayNonce = req.getHeader("Wechatpay-Nonce");
            String wechatSignature = req.getHeader("Wechatpay-Signature");
            String wechatTimestamp = req.getHeader("Wechatpay-Timestamp");
            // 构造 RequestParam
            com.wechat.pay.java.core.notification.RequestParam requestParam = new com.wechat.pay.java.core.notification.RequestParam.Builder()
                    .serialNumber(wechatPaySerial)
                    .nonce(wechatpayNonce)
                    .signature(wechatSignature)
                    .timestamp(wechatTimestamp)
                    .body(requestBody)
                    .build();
            // 如果已经初始化了 RSAAutoCertificateConfig，可直接使用
            // 没有的话，则构造一个
            NotificationConfig config = new RSAAutoCertificateConfig.Builder()
                    .merchantId(WechatUtil.getMerchantId())
                    .privateKeyFromPath(WechatUtil.getPrivateKeyPath())
                    .merchantSerialNumber(WechatUtil.getMerchantSerialNumber())
                    .apiV3Key(WechatUtil.getApiV3key())
                    .build();

            // 初始化 NotificationParser
            NotificationParser parser = new NotificationParser(config);
            try {
                // 以支付通知回调为例，验签、解密并转换成 Transaction
                Transaction transaction = parser.parse(requestParam, Transaction.class);
                //处理业务逻辑
                LambdaQueryWrapper<UserhomeOrder> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(UserhomeOrder::getOrderNum, transaction.getOutTradeNo());
                UserhomeOrder userhomeOrder = userhomeOrderService.getOne(queryWrapper);
                Integer tprice = (int) (userhomeOrder.getTprice() * 100);
                if (!tprice.equals(transaction.getAmount().getTotal())) {
                    return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
                }
                userhomeOrderService.payStatus(1, transaction.getOutTradeNo());
                // 如果处理失败，应返回 4xx/5xx 的状态码，例如 500 INTERNAL_SERVER_ERROR
                if (false) {
                    return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
                }
            } catch (ValidationException e) {
                // 签名验证失败，返回 401 UNAUTHORIZED 状态码
                return "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA[FAIL]]></return_msg></xml>";
            }
        }
        // 处理成功，返回 200 OK 状态码
        return "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
    }

    @RequestMapping(value = "/ali/notify", method = {RequestMethod.GET,RequestMethod.POST})
    @Transactional(rollbackFor = Exception.class)
    public String aliNotify(HttpServletRequest req) throws InstantiationException, IllegalAccessException {
        String outTradeNo = req.getParameter("out_trade_no");
        String tradeStatus = req.getParameter("trade_status");
        String totalAmount = req.getParameter("total_amount");
        if (tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED")) {
            try {
                // 支付宝公钥
                String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgQjISpChzBZmka+XkbCKAViK7e7bncs71iHsphWR9Qu4yNljQjTmz+o4oFEx/buZ73XW3GJhaXW5XTHzB9tLAgTIrmuiAKTrBwsZM4QrRfKjn/CQ6mXuiB10YY6OocfQ5ZZbG3tz9ukUI9XQUVDZR0SegprlucIkEDywMSAwPXhfvCezqLhwEH8N2XckISldZYXiOZObwpIR1cGFCDGfvSzU5T2dyrPUy0/aYGutCkvS/C5dOqGkx3f714jTPRImoZqomWyuKgsXjjhSzlA3YGEic1MdqS6QWPlGwL9qhyHlIAuAvr1xrlfZ1YMxGwwaEzt+9ordNeWbnObVyfwHQQIDAQAB";
                // 编码格式
                String charset = "utf-8";
                // 签名方式
                String sign_type = "RSA2";
                LinkedHashMap<String, String> map = new LinkedHashMap<>();
                Map<String, String[]> requestParams = req.getParameterMap();
                for (String name : requestParams.keySet()) {
                    String[] values = requestParams.get(name);
                    String valueStr = "";
                    for (int i = 0; i < values.length; i++) {
                        valueStr = (i == values.length - 1) ? valueStr + values[i]
                                : valueStr + values[i] + ",";
                    }
                    map.put(name, valueStr);
                }
                //System.out.println(map);
                // 验签方法
                boolean signVerified = AlipaySignature.rsaCheckV1(map, publicKey, charset, sign_type);
                if (signVerified) {
                    //处理业务逻辑
                    LambdaQueryWrapper<UserhomeOrder> queryWrapper = new LambdaQueryWrapper<>();
                    queryWrapper.eq(UserhomeOrder::getOrderNum, outTradeNo);
                    UserhomeOrder userhomeOrder = userhomeOrderService.getOne(queryWrapper);
                    String tprice = String.format("%.2f",userhomeOrder.getTprice());
                    if (!tprice.equals(totalAmount)) {
                        return "error";
                    }
                    userhomeOrderService.payStatus(1, outTradeNo);
                } else {
                    return "error";
                }
            } catch (ValidationException e) {
                // 签名验证失败，返回 401 UNAUTHORIZED 状态码
                return "error";
            } catch (AlipayApiException e) {
                e.printStackTrace();
                return "error";
            }
            return "success";
        }
        // 处理成功，返回 200 OK 状态码
        return "error";
    }
}